package com.ns.sbs.oauth.acc4auth.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.ns.basic.dict.service.IDictEntryService;
import com.ns.basic.server.service.IServerMenuService;
import com.ns.core.annotations.ReqLog;
import com.ns.core.utils.StpUtil;
import com.ns.core.utils.sg.NbUtil;
import com.ns.core.utils.sg.ResultError;
import com.ns.core.utils.sg.ResultOk;
import com.ns.core.vo.au.SsoUserVO;
import com.ns.core.vo.login.ServObjVO;
import com.ns.core.vo.login.SucObjVO;
import com.ns.sbs.oauth.acc.entry.Acc2Server;
import com.ns.sbs.oauth.acc.service.IAcc2ServerService;
import com.ns.sbs.oauth.acc4auth.service.IAccAuthService;
import com.ns.sbs.oauth.menu.service.IMenuService;
import com.ns.sbs.oauth.rent.service.IRentService;
import com.ns.sbs.oauth.role.service.IRoleService;
import com.ns.sbs.oauth.role.vo.RoleEntryVO;
import com.ns.sbs.oauth.role4permission.service.RolePermissionServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Admin账号相关操作
 *
 * @author lw
 */
@RestController
@RequestMapping("/sso/")
@RequiredArgsConstructor
@CrossOrigin
public class SsoController {

    private final IAccAuthService accAdminService;

    private final IMenuService menuService;

    private final IDictEntryService dictEntryService;

    private final RolePermissionServiceImpl rolePermissionService;

    private final IAcc2ServerService acc2ServerService;

    private final IRoleService roleService;

    private final IServerMenuService serverMenuService;

    private final IRentService rentService;

    /**
     * 账户、密码登录
     *
     * @param user 参数
     * @param pwd  参数
     */
    @GetMapping("login")
    @ReqLog(module = "权限模块", name = "登录", authFlag = false, isRecordFlag = true)
    @SentinelResource(value = "qps-max-1")
    public ResultOk doLogin(String user, String pwd) {
        // 1、验证参数
        if (NbUtil.hasNull(user, pwd)) {
            return ResultOk.getError("请提供用户名与密码参数");
        }
        return ResultOk.getSuccessData(accAdminService.doLogin(user, pwd));
    }

    /**
     * 退出登录
     */
    @GetMapping("logout")
    @ReqLog(module = "登录模块", name = "退出", isRecordFlag = true)
    public ResultOk doExit() {
        Long loginUserId = StpUtil.getLoginUserId();
        if (Objects.nonNull(loginUserId)) {
            StpUtil.logout(loginUserId);
        }
        return ResultOk.getSuccess();
    }

    /**
     * 获取会话信息
     */
    @GetMapping("getInfo")
    @ReqLog(module = "登录模块", name = "获取会话")
    public ResultOk getLoginInfo() {
        // 当前admin
        SsoUserVO curr = StpUtil.getCurUser();
        if (Objects.nonNull(curr)) {
            SucObjVO sucObjVO = new SucObjVO();
            // 获取用户角色
            Acc2Server acc2Server = acc2ServerService.getByAccAndSid(curr.getId(), StpUtil.getSid());
            if (Objects.isNull(acc2Server)) {
                throw new ResultError("该用户赞绑定角色,请联系管理员！");
            }
            // 当前用户权限
            List<Long> holdMenus = getRolePermission(acc2Server.getRoleId());
            if (CollectionUtils.isEmpty(holdMenus)) {
                throw new ResultError("该用户赞无任何权限,请联系管理员！");
            }
            // 权限菜单
            sucObjVO.setM(menuService.getDynamicMenu(holdMenus));
            // 权限菜单码
            sucObjVO.setAuthCodes(menuService.getMenuCode(holdMenus));
            // 字典
            sucObjVO.setGd(dictEntryService.listBy());
            // 查询账户服务
            List<ServObjVO> svs = acc2ServerService.getByAccId(curr.getId());
            if (CollectionUtils.isEmpty(svs)) {
                throw new ResultError("该用户暂无服务可用,请联系管理员!");
            }
            sucObjVO.setCurs(svs);
            return ResultOk.getSuccessData(sucObjVO);
        } else {
            return ResultOk.getNotLogin();
        }
    }

    /**
     * 读取角色权限
     *
     * @param roleId 角色id
     * @return List
     */
    private List<Long> getRolePermission(Long roleId) {
        List<Long> rpm = new ArrayList<>();
        // 获取角色，如果角色中isLock ==1 时，则为整个租户权限；否则需要帅选权限
        RoleEntryVO role = roleService.getById(roleId);
        if (Objects.isNull(role)) {
            return rpm;
        }
        // 服务权限
        List<List<String>> permissions = serverMenuService.getPermissions(role.getSid());
        if (CollectionUtils.isEmpty(permissions)) {
            return rpm;
        }
        Set<Long> serverPermissions = parsePermissions(permissions);
        // 租户权限
        List<List<String>> rentPermission = rentService.getRentPermission(role.getRid());
        if (CollectionUtils.isEmpty(rentPermission)) {
            return rpm;
        }
        Set<Long> rentPermissions = parsePermissions(rentPermission);
        // 角色权限
        List<Long> rolePermissions;
        if (Objects.equals(role.getIsLock(), 1)) {
            rolePermissions = new ArrayList<>(rentPermissions);
        } else {
            rolePermissions = rolePermissionService.getCodeByRoleId(roleId);
        }
        if (CollectionUtils.isEmpty(rolePermissions)) {
            return rpm;
        }

        // 筛选权限
        for (Long rolePermission : rolePermissions) {
            if (serverPermissions.contains(rolePermission) && rentPermissions.contains(rolePermission)) {
                rpm.add(rolePermission);
            }
        }
        return rpm;
    }

    /**
     * 读取租户权限
     *
     * @param permissions 登录日志模块
     * @return Set
     */
    private Set<Long> parsePermissions(List<List<String>> permissions) {
        Set<Long> pmsSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(permissions)) {
            for (List<String> pms : permissions) {
                pmsSet.addAll(pms.stream().map(Long::parseLong).collect(Collectors.toSet()));
            }
        }
        return pmsSet;
    }
}
